#ifndef NMC_FILEUTIL_HPP
#define NMC_FILEUTIL_HPP

#include "exception.hpp"

#include <fstream>
#include <string>

namespace nmc
{
	inline int readInt(std::istream &is)
	{
		int x;
		is.read((char *)&x, sizeof(x));
		return x;
	}

	inline void writeInt(std::ostream &os, int x)
	{
		os.write((char *)&x, sizeof(x));
	}

	inline void writeString(std::ostream &os, const std::string &s)
	{
		writeInt(os, s.size());
		os.write(s.c_str(), s.size());
	}

	inline std::string readString(std::istream &is)
	{
		int size = readInt(is);
		char *cstr = new char[size + 1];
		is.read(cstr, size);
		cstr[size] = '\0';
		std::string result(cstr);
		delete[] cstr;
		return result;
	}

	inline std::string loadFile(const std::string &fileName, bool fullpath = false)
	{
		std::ifstream is(fileName.c_str());
		
		if (!is.good())
		{
			throw NMC_EXCEPTION("Unable to open " + fileName);
		}
		
		std::string result;

		while (is.good()) {
			int c = is.get();
			if (c >= 0) {
				result += (unsigned char)c;
			} else {
				break;
			}
		}

		return result;
	}

    inline std::vector<std::string> tokenize(const std::string &input, 
		                                     const std::string separator, 
											 bool ignoreEmpty = false)
	{
		bool done = false;
		int pos = 0;
		int lastpos = 0;
		
		std::vector<std::string> result;

		while(!done)
		{
			pos = input.find(separator, lastpos);

			if (pos == std::string::npos)
			{
				done = true;
				pos = input.length();
			}

			std::string sub = input.substr(lastpos, pos - lastpos);
		
			if (sub.size() > 0 || !ignoreEmpty)
			{
				result.push_back(sub);
			}

			lastpos = pos + separator.length();
		}

		return result;
	}
}

#endif